/**
 * 优化的基础服务类
 * 包含缓存、重试、并发控制、性能监控等优化
 */

interface CacheEntry {
  data: any;
  timestamp: number;
  etag?: string;
}

interface RequestConfig {
  cache?: boolean;
  cacheTTL?: number;
  retry?: number;
  timeout?: number;
  priority?: 'high' | 'normal' | 'low';
}

class RequestQueue {
  private high: Array<() => Promise<any>> = [];
  private normal: Array<() => Promise<any>> = [];
  private low: Array<() => Promise<any>> = [];
  private running = 0;
  private maxConcurrent = 6;

  async add<T>(fn: () => Promise<T>, priority: 'high' | 'normal' | 'low' = 'normal'): Promise<T> {
    return new Promise((resolve, reject) => {
      const task = async () => {
        this.running++;
        try {
          const result = await fn();
          resolve(result);
        } catch (error) {
          reject(error);
        } finally {
          this.running--;
          this.processNext();
        }
      };

      // 根据优先级添加到队列
      switch (priority) {
        case 'high':
          this.high.push(task);
          break;
        case 'low':
          this.low.push(task);
          break;
        default:
          this.normal.push(task);
      }

      this.processNext();
    });
  }

  private processNext() {
    if (this.running >= this.maxConcurrent) return;

    let task: (() => Promise<any>) | undefined;
    
    if (this.high.length > 0) {
      task = this.high.shift();
    } else if (this.normal.length > 0) {
      task = this.normal.shift();
    } else if (this.low.length > 0) {
      task = this.low.shift();
    }

    if (task) {
      task();
    }
  }
}

export class OptimizedBaseService {
  private cache = new Map<string, CacheEntry>();
  private requestQueue = new RequestQueue();
  private abortControllers = new Map<string, AbortController>();
  
  // 性能监控
  private metrics = {
    totalRequests: 0,
    cacheHits: 0,
    cacheMisses: 0,
    failedRequests: 0,
    avgResponseTime: 0,
  };

  protected getHeaders(): HeadersInit {
    const headers: HeadersInit = {
      'Content-Type': 'application/json',
    };

    const token = localStorage.getItem('token');
    if (token) {
      headers['Authorization'] = `Bearer ${token}`;
    }

    return headers;
  }

  /**
   * 生成缓存键
   */
  private getCacheKey(url: string, params?: any): string {
    return `${url}${params ? JSON.stringify(params) : ''}`;
  }

  /**
   * 检查缓存
   */
  private checkCache(key: string, ttl: number): CacheEntry | null {
    const cached = this.cache.get(key);
    if (cached) {
      const age = Date.now() - cached.timestamp;
      if (age < ttl) {
        this.metrics.cacheHits++;
        return cached;
      }
      // 缓存过期，删除
      this.cache.delete(key);
    }
    this.metrics.cacheMisses++;
    return null;
  }

  /**
   * 存储缓存
   */
  private setCache(key: string, data: any, etag?: string) {
    // 限制缓存大小
    if (this.cache.size > 100) {
      const firstKey = this.cache.keys().next().value;
      this.cache.delete(firstKey);
    }
    
    this.cache.set(key, {
      data,
      timestamp: Date.now(),
      etag
    });
  }

  /**
   * 带重试的请求
   */
  private async fetchWithRetry(
    url: string,
    options: RequestInit,
    retryCount = 3,
    timeout = 10000
  ): Promise<Response> {
    const requestId = `${url}-${Date.now()}`;
    
    for (let i = 0; i <= retryCount; i++) {
      const controller = new AbortController();
      this.abortControllers.set(requestId, controller);
      
      const timeoutId = setTimeout(() => controller.abort(), timeout);
      
      try {
        const startTime = performance.now();
        const response = await fetch(url, {
          ...options,
          signal: controller.signal
        });
        
        // 更新性能指标
        const responseTime = performance.now() - startTime;
        this.updateMetrics(responseTime, true);
        
        clearTimeout(timeoutId);
        this.abortControllers.delete(requestId);
        
        return response;
      } catch (error: any) {
        clearTimeout(timeoutId);
        this.abortControllers.delete(requestId);
        
        // 如果是最后一次重试，抛出错误
        if (i === retryCount) {
          this.updateMetrics(0, false);
          
          if (error.name === 'AbortError') {
            throw new Error(`Request timeout after ${timeout}ms`);
          }
          throw error;
        }
        
        // 指数退避
        await new Promise(resolve => setTimeout(resolve, Math.pow(2, i) * 1000));
      }
    }
    
    throw new Error('Max retries reached');
  }

  /**
   * 更新性能指标
   */
  private updateMetrics(responseTime: number, success: boolean) {
    this.metrics.totalRequests++;
    
    if (success) {
      // 计算平均响应时间
      const prevAvg = this.metrics.avgResponseTime;
      const prevCount = this.metrics.totalRequests - this.metrics.failedRequests - 1;
      this.metrics.avgResponseTime = (prevAvg * prevCount + responseTime) / (prevCount + 1);
    } else {
      this.metrics.failedRequests++;
    }
  }

  /**
   * 获取性能指标
   */
  public getMetrics() {
    return {
      ...this.metrics,
      cacheHitRate: this.metrics.totalRequests > 0 
        ? (this.metrics.cacheHits / (this.metrics.cacheHits + this.metrics.cacheMisses)) * 100 
        : 0,
      successRate: this.metrics.totalRequests > 0
        ? ((this.metrics.totalRequests - this.metrics.failedRequests) / this.metrics.totalRequests) * 100
        : 100
    };
  }

  /**
   * 清理缓存
   */
  public clearCache() {
    this.cache.clear();
  }

  /**
   * 取消所有请求
   */
  public cancelAllRequests() {
    this.abortControllers.forEach(controller => controller.abort());
    this.abortControllers.clear();
  }

  protected async handleResponse<T>(response: Response): Promise<T> {
    if (!response.ok) {
      const errorText = await response.text();
      let errorMessage = `HTTP ${response.status}: ${response.statusText}`;
      
      try {
        const errorData = JSON.parse(errorText);
        errorMessage = errorData.message || errorData.detail || errorMessage;
      } catch {
        if (errorText) {
          errorMessage = errorText;
        }
      }
      
      throw new Error(errorMessage);
    }

    const text = await response.text();
    if (!text) {
      return {} as T;
    }

    try {
      return JSON.parse(text);
    } catch {
      return text as unknown as T;
    }
  }

  protected buildQueryString(params: Record<string, any>): string {
    const searchParams = new URLSearchParams();
    
    Object.entries(params).forEach(([key, value]) => {
      if (value !== undefined && value !== null) {
        if (Array.isArray(value)) {
          value.forEach(v => searchParams.append(key, String(v)));
        } else if (typeof value === 'object') {
          searchParams.append(key, JSON.stringify(value));
        } else {
          searchParams.append(key, String(value));
        }
      }
    });

    const queryString = searchParams.toString();
    return queryString ? `?${queryString}` : '';
  }

  /**
   * 优化的 GET 请求
   */
  protected async get<T>(
    url: string, 
    params?: Record<string, any>,
    config: RequestConfig = {}
  ): Promise<T> {
    const {
      cache = true,
      cacheTTL = 5 * 60 * 1000, // 默认5分钟
      retry = 2,
      timeout = 10000,
      priority = 'normal'
    } = config;

    const queryString = params ? this.buildQueryString(params) : '';
    const fullUrl = `${url}${queryString}`;
    const cacheKey = this.getCacheKey(url, params);

    // 检查缓存
    if (cache) {
      const cached = this.checkCache(cacheKey, cacheTTL);
      if (cached) {
        return cached.data;
      }
    }

    // 使用请求队列
    return this.requestQueue.add(async () => {
      const response = await this.fetchWithRetry(
        fullUrl,
        {
          method: 'GET',
          headers: this.getHeaders(),
        },
        retry,
        timeout
      );

      const data = await this.handleResponse<T>(response);
      
      // 存储缓存
      if (cache && response.ok) {
        this.setCache(cacheKey, data, response.headers.get('etag') || undefined);
      }

      return data;
    }, priority);
  }

  /**
   * 优化的 POST 请求
   */
  protected async post<T>(
    url: string, 
    data?: any,
    config: RequestConfig = {}
  ): Promise<T> {
    const {
      retry = 2,
      timeout = 15000,
      priority = 'normal'
    } = config;

    return this.requestQueue.add(async () => {
      const response = await this.fetchWithRetry(
        url,
        {
          method: 'POST',
          headers: this.getHeaders(),
          body: data ? JSON.stringify(data) : undefined,
        },
        retry,
        timeout
      );

      return this.handleResponse<T>(response);
    }, priority);
  }

  /**
   * 批量请求优化
   */
  protected async batchRequest<T>(
    requests: Array<{
      url: string;
      method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
      data?: any;
      params?: Record<string, any>;
    }>
  ): Promise<T[]> {
    const promises = requests.map(req => {
      switch (req.method || 'GET') {
        case 'GET':
          return this.get(req.url, req.params);
        case 'POST':
          return this.post(req.url, req.data);
        case 'PUT':
          return this.put(req.url, req.data);
        case 'DELETE':
          return this.delete(req.url);
        default:
          return this.get(req.url, req.params);
      }
    });

    return Promise.all(promises) as Promise<T[]>;
  }

  protected async put<T>(
    url: string, 
    data?: any,
    config: RequestConfig = {}
  ): Promise<T> {
    const {
      retry = 2,
      timeout = 10000,
      priority = 'normal'
    } = config;

    return this.requestQueue.add(async () => {
      const response = await this.fetchWithRetry(
        url,
        {
          method: 'PUT',
          headers: this.getHeaders(),
          body: data ? JSON.stringify(data) : undefined,
        },
        retry,
        timeout
      );

      return this.handleResponse<T>(response);
    }, priority);
  }

  protected async delete<T>(
    url: string,
    config: RequestConfig = {}
  ): Promise<T> {
    const {
      retry = 2,
      timeout = 10000,
      priority = 'normal'
    } = config;

    return this.requestQueue.add(async () => {
      const response = await this.fetchWithRetry(
        url,
        {
          method: 'DELETE',
          headers: this.getHeaders(),
        },
        retry,
        timeout
      );

      // 清理相关缓存
      this.cache.forEach((_, key) => {
        if (key.startsWith(url)) {
          this.cache.delete(key);
        }
      });

      return this.handleResponse<T>(response);
    }, priority);
  }

  protected async patch<T>(
    url: string, 
    data?: any,
    config: RequestConfig = {}
  ): Promise<T> {
    const {
      retry = 2,
      timeout = 10000,
      priority = 'normal'
    } = config;

    return this.requestQueue.add(async () => {
      const response = await this.fetchWithRetry(
        url,
        {
          method: 'PATCH',
          headers: this.getHeaders(),
          body: data ? JSON.stringify(data) : undefined,
        },
        retry,
        timeout
      );

      return this.handleResponse<T>(response);
    }, priority);
  }
}

// 导出单例实例
export const optimizedBaseService = new OptimizedBaseService();